namespace Known.SqlSugar;

class SqlSugarQueryBuilder<T>(SqlSugarDatabase db) : IQueryBuilder<T> where T : class, new()
{
    private readonly SqlSugarDatabase db = db;
    private ISugarQueryable<T> query = db.sugar.Queryable<T>();

    public string WhereSql { get; private set; }
    public Dictionary<string, object> Parameters { get; private set; }

    public IQueryBuilder<TItem> Select<TItem>(Expression<Func<T, TItem>> selector) where TItem : class, new()
    {
        var builder = new SqlSugarQueryBuilder<TItem>(db);
        builder.query = query.Select(selector);
        return builder;
    }

    public IQueryBuilder<T> Where(Expression<Func<T, bool>> predicate)
    {
        query = query.Where(predicate);
        return this;
    }

    public IQueryBuilder<T> GroupBy(Expression<Func<T, object>> selector)
    {
        query = query.GroupBy(selector);
        return this;
    }

    public IQueryBuilder<T> OrderBy(Expression<Func<T, object>> selector)
    {
        query = query.OrderBy(selector);
        return this;
    }

    public IQueryBuilder<T> ThenBy(Expression<Func<T, object>> selector) => OrderBy(selector);

    public IQueryBuilder<T> OrderByDescending(Expression<Func<T, object>> selector)
    {
        query = query.OrderByDescending(selector);
        return this;
    }

    public IQueryBuilder<T> ThenByDescending(Expression<Func<T, object>> selector) => OrderByDescending(selector);

    public Task<int> CountAsync() => query.CountAsync();

    public async Task<bool> ExistsAsync()
    {
        var count = await query.CountAsync();
        return count > 0;
    }

    public Task<T> FirstAsync() => FirstAsync<T>();

    public Task<TItem> FirstAsync<TItem>()
    {
        var sql = query.ToSql();
        return db.sugar.QueryAsync<TItem>(sql.Key, sql.Value);
    }

    public Task<List<T>> ToListAsync() => ToListAsync<T>();

    public Task<List<TItem>> ToListAsync<TItem>()
    {
        var sql = query.ToSql();
        return db.sugar.QueryListAsync<TItem>(sql.Key, sql.Value);
    }
}